package com.kizuki.thread;

import org.junit.Test;

import java.util.Objects;
import java.util.concurrent.CompletableFuture;

/**
 * 并发重点，多使用
 */
public class TestCompletableFuture {

    @Test
    public void testWhenComplete() {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("开始任务");
            int i = 10/0;
            return 200;
        });

        // 类似于 es6 promise, whenComplete不消费异常(需要搭配exceptionally)
        CompletableFuture<Integer> f1 = future.whenComplete((u, t) -> {
            System.out.println("u:" + u); // 成功的返回值
            System.out.println("t:" + t); // 错误信息  java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
        }).exceptionally((e) -> {
            System.out.println(e.getMessage()); // java.lang.ArithmeticException: / by zero
            return 404;
        });

        //多个future 阻塞get/join
        CompletableFuture.allOf(f1).join();
        System.out.println(f1.join());
    }

    @Test
    public void testHandle() {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("开始任务");
            int i = 10/0;
            return 200;
        //handle消费异常，不需要exceptionally
        }).handle((res, exption) -> {
            if (Objects.nonNull(exption)) {
                System.out.println("异常：" + exption);
                return 0;
            } else {
                System.out.println("res：" + res);
                return res;
            }
        });

        CompletableFuture.allOf(future).join();
        System.out.println("最后的结果为：" + future.join());
    }


    @Test
    public void testThenApply(){
        CompletableFuture<Integer> first = CompletableFuture.supplyAsync(() -> 100);
        // function转换类型, 类似stream的map
        CompletableFuture<String> second = first.thenApply((num) -> "得到" + num + "元！");
        System.out.println("结果：" + second.join());
    }

    /**
     * 用来连接两个CompletableFuture，是生成一个新的CompletableFuture
     */
    @Test
    public void testThenCompose(){
        CompletableFuture<Integer> first = CompletableFuture.supplyAsync(() -> 100);
        CompletableFuture<String> second = first.thenCompose((num) -> CompletableFuture.supplyAsync(() -> "得到" + num + "元！"));
        System.out.println("结果：" + second.join());
    }
}
